﻿using System;
using System.Collections.Generic;
using System.Linq;
using Pogo.Data;
using Pogo.Properties;

namespace Pogo
{
   public class Plug : PogoObject
   {
      private readonly RestService cloudService;
      private List<Device> _devices;
      private string currentPassword;
      private string currentUserID;

      public Plug(string serviceUrl = null)
      {
         cloudService = new RestService(serviceUrl);
      }

      // http://stackoverflow.com/questions/2389290/how-to-load-a-separate-application-settings-file-dynamically-and-merge-with-curr
      private string Email
      {
         get { return Settings.Default.UserID.DecryptString().ToInsecureString(); }
         set { Settings.Default.UserID = value.ToSecureString().EncryptString(); }
      }

      private string Password
      {
         get { return Settings.Default.Password.DecryptString().ToInsecureString(); }
         set { Settings.Default.Password = value.ToSecureString().EncryptString(); }
      }

      internal override PogoObject Parent
      {
         get { return null; }
         set { }
      }

      protected override string AuthToken { get; set; }

      public override bool LoggedIn
      {
         get { return AuthToken != null; }
      }

      public IUser CurrentUser
      {
         get { return CloudService.GetUser<User>(AuthToken); }
      }

      public IVersionInfo Version
      {
         get { return CloudService.GetVersion<VersionInfo>(); }
      }

      public IEnumerable<IDevice> Devices
      {
         get
         {
            if (_devices == null)
            {
               _devices = CloudService.ListDevices<List<Device>>(AuthToken);

               foreach (Device device in _devices)
               {
                  device.Parent = this;

                  foreach (Service service in device.Services)
                  {
                     service.Parent = this;
                     service.DeviceID = device.DeviceID;
                  }
               }
            }

            return _devices;
         }
      }

      public IEnumerable<IFileService> FileServices
      {
         get { return Devices.SelectMany(d => d.FileServices).ToList(); }
      }

      internal RestService CloudService
      {
         get { return cloudService; }
      }

      internal Device GetDevice(string deviceID)
      {
         return _devices.FirstOrDefault(d => d.DeviceID == deviceID);
      }

      internal Service GetService(string serviceID)
      {
         return FileServices.Cast<Service>().FirstOrDefault(s => s.ServiceID == serviceID);
      }

      public bool Login()
      {
         if (string.IsNullOrEmpty(currentUserID))
            currentUserID = Email;
         if (string.IsNullOrEmpty(currentPassword))
            currentPassword = Password;

         return Login(currentUserID, currentPassword);
      }

      public bool Login(string email, string password, bool storeIfSuccessful = false)
      {
         if (string.IsNullOrEmpty(email)) throw new ArgumentNullException("email");
         if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password");

         currentUserID = email;
         currentPassword = password;

         LoginResult result = CloudService.LoginUser<LoginResult>(currentUserID, currentPassword);
         if (result != null)
         {
            AuthToken = result.Valtoken;

            if (storeIfSuccessful)
            {
               Email = currentUserID;
               Password = currentPassword;
            }
         }

         return result != null;
      }
   }
}